package api

import (
	"fmt"
	"net/http"
	"pids-cloud-server/app/common"
	"pids-cloud-server/entity"
	"pids-cloud-server/logging"
	"pids-cloud-server/utils"
	"strings"

	"github.com/gin-gonic/gin"
	"github.com/gosnmp/gosnmp"
	"gorm.io/gorm"
)

// SyncToSnmpInfo 手动同步数据到m_snmp_info表
// @Summary 手动同步数据到SNMP信息表
// @Description 将服务器、播控设备、PDU、交换机数据批量同步到m_snmp_info表中
// @Tags 数据同步
// @Accept json
// @Produce json
// @Param syncRequest body entity.SyncRequest false "同步请求参数，不传则同步所有类型"
// @Success 200 {object} common.Result{data=entity.SyncResponse} "同步成功"
// @Failure 400 {object} common.Result "参数错误"
// @Failure 500 {object} common.Result "同步失败"
// @Router /api/sync/snmp [post]
func SyncToSnmpInfo(c *gin.Context) {
	var syncRequest entity.SyncRequest

	// 如果没有传递参数，默认同步所有类型
	if err := c.ShouldBindJSON(&syncRequest); err != nil {
		// 参数解析失败时，默认同步所有类型
		syncRequest = entity.SyncRequest{
			SyncDevices:  true,
			SyncServers:  true,
			SyncPdus:     true,
			SyncSwitches: true,
		}
	}

	// 如果所有同步选项都为false，则默认同步所有
	if !syncRequest.SyncDevices && !syncRequest.SyncServers &&
		!syncRequest.SyncPdus && !syncRequest.SyncSwitches {
		syncRequest.SyncDevices = true
		syncRequest.SyncServers = true
		syncRequest.SyncPdus = true
		syncRequest.SyncSwitches = true
	}

	db := utils.GetDB()
	if db == nil {
		common.ErrorResponse(c, http.StatusInternalServerError, "数据库连接失败")
		return
	}

	response := entity.SyncResponse{}
	var allSnmpInfos []entity.SnmpInfo
	var errors []string

	// 1. 同步设备信息（pids_device_info）
	if syncRequest.SyncDevices {
		deviceInfos, count, err := syncDeviceInfo(db)
		if err != nil {
			errors = append(errors, fmt.Sprintf("设备信息同步失败: %v", err))
			logging.Error("设备信息同步失败", err)
		} else {
			allSnmpInfos = append(allSnmpInfos, deviceInfos...)
			response.DeviceCount = count
		}
	}

	// 2. 同步服务器信息（pids_server_info）
	if syncRequest.SyncServers {
		serverInfos, count, err := syncServerInfo(db)
		if err != nil {
			errors = append(errors, fmt.Sprintf("服务器信息同步失败: %v", err))
			logging.Error("服务器信息同步失败", err)
		} else {
			allSnmpInfos = append(allSnmpInfos, serverInfos...)
			response.ServerCount = count
		}
	}

	// 3. 同步PDU信息（pids_pdu_info）
	if syncRequest.SyncPdus {
		pduInfos, count, err := syncPduInfo(db)
		if err != nil {
			errors = append(errors, fmt.Sprintf("PDU信息同步失败: %v", err))
			logging.Error("PDU信息同步失败", err)
		} else {
			allSnmpInfos = append(allSnmpInfos, pduInfos...)
			response.PduCount = count
		}
	}

	// 4. 同步交换机信息（pids_switch_info）
	if syncRequest.SyncSwitches {
		switchInfos, count, err := syncSwitchInfo(db)
		if err != nil {
			errors = append(errors, fmt.Sprintf("交换机信息同步失败: %v", err))
			logging.Error("交换机信息同步失败", err)
		} else {
			allSnmpInfos = append(allSnmpInfos, switchInfos...)
			response.SwitchCount = count
		}
	}

	response.TotalCount = len(allSnmpInfos)

	// 批量插入到m_snmp_info表
	if len(allSnmpInfos) > 0 {
		// 使用事务处理批量插入
		tx := db.Begin()

		successCount := 0
		failedCount := 0

		for _, snmpInfo := range allSnmpInfos {
			// 检查IP是否已存在，避免重复插入
			var existingCount int64
			tx.Model(&entity.SnmpInfo{}).Where("ip = ?", snmpInfo.IP).Count(&existingCount)

			if existingCount == 0 {
				// 新增SNMP信息
				if err := tx.Create(&snmpInfo).Error; err != nil {
					failedCount++
					logging.Errorf("插入SNMP信息失败 IP: %s, 错误: %v", snmpInfo.IP, err)
				} else {
					successCount++
					// 新增成功后，根据model类型生成对应的SnmpOid记录
					if err := createSnmpOidsForNewDevice(tx, snmpInfo.IP, string(snmpInfo.Model)); err != nil {
						logging.Errorf("为设备 %s 创建SnmpOid失败: %v", snmpInfo.IP, err)
					}
				}
			} else {
				// IP已存在，更新记录
				if err := tx.Model(&entity.SnmpInfo{}).Where("ip = ?", snmpInfo.IP).Updates(&snmpInfo).Error; err != nil {
					failedCount++
					logging.Errorf("更新SNMP信息失败 IP: %s, 错误: %v", snmpInfo.IP, err)
				} else {
					successCount++
				}
			}
		}

		response.SuccessCount = successCount
		response.FailedCount = failedCount

		if failedCount > 0 {
			tx.Rollback()
			errorMsg := fmt.Sprintf("数据同步部分失败，成功: %d, 失败: %d", successCount, failedCount)
			if len(errors) > 0 {
				errorMsg += "; " + strings.Join(errors, "; ")
			}
			common.ErrorResponse(c, http.StatusInternalServerError, errorMsg)
			return
		} else {
			tx.Commit()
		}
	}

	if len(errors) > 0 {
		errorMsg := "同步过程中出现错误: " + strings.Join(errors, "; ")
		common.ErrorResponse(c, http.StatusInternalServerError, errorMsg)
		return
	}

	logging.Infof("数据同步完成，总计: %d, 成功: %d, 失败: %d",
		response.TotalCount, response.SuccessCount, response.FailedCount)

	common.SuccessResponse(c, response)
}

// syncDeviceInfo 同步设备信息
func syncDeviceInfo(db interface{}) ([]entity.SnmpInfo, int, error) {
	gormDB := db.(*gorm.DB)
	var devices []entity.DeviceInfo

	// 只查询有IP地址且非车载设备的设备（排除district=4的车载设备）
	if err := gormDB.Where("ip != '' AND ip IS NOT NULL AND (district IS NULL OR district != 4)").Find(&devices).Error; err != nil {
		return nil, 0, err
	}

	var snmpInfos []entity.SnmpInfo
	version := int(gosnmp.Version2c)
	for _, device := range devices {
		if device.IP == "" {
			continue
		}

		// 根据设备类型映射到SNMP信息类型
		var snmpType entity.DeviceType
		switch device.Type {
		case 1: // LCD
			snmpType = entity.BroadcastController // 播控器
		case 2: // LED
			snmpType = 5 // LED设备（暂时使用数字，如需要可在DeviceType中添加LED常量）
		default:
			snmpType = entity.BroadcastController // 默认为播控器
		}

		// 根据设备类型设置不同的默认值
		var community string
		var model entity.ModelType

		if device.Type == 2 { // LED设备
			community = "" // LED设备不需要填写Community
			model = ""     // LED设备默认""
		} else {
			community = "public"  // 其他设备默认public
			model = entity.UBUNTU // 播控器默认Ubuntu
		}

		snmpInfo := entity.SnmpInfo{
			IP:         device.IP,
			Community:  community, // 根据设备类型设置
			Version:    version,   // 默认版本2
			Model:      model,     // 根据设备类型设置模型
			Devicetype: snmpType,
			Enable:     true, // 默认启用
		}
		snmpInfos = append(snmpInfos, snmpInfo)
	}

	return snmpInfos, len(snmpInfos), nil
}

// syncServerInfo 同步服务器信息
func syncServerInfo(db interface{}) ([]entity.SnmpInfo, int, error) {
	gormDB := db.(*gorm.DB)
	var servers []entity.ServerInfo

	// 只查询有IP地址的服务器
	if err := gormDB.Where("ip != '' AND ip IS NOT NULL").Find(&servers).Error; err != nil {
		return nil, 0, err
	}

	var snmpInfos []entity.SnmpInfo
	version := int(gosnmp.Version2c)
	for _, server := range servers {
		if server.IP == "" {
			continue
		}

		snmpInfo := entity.SnmpInfo{
			IP:         server.IP,
			Community:  "public",      // 默认团体名
			Version:    version,       // 默认版本2
			Model:      entity.UBUNTU, // 服务器默认Ubuntu
			Devicetype: entity.Server, // 服务器类型
			Enable:     true,          // 默认启用
		}
		snmpInfos = append(snmpInfos, snmpInfo)
	}

	return snmpInfos, len(snmpInfos), nil
}

// syncPduInfo 同步PDU信息
func syncPduInfo(db interface{}) ([]entity.SnmpInfo, int, error) {
	gormDB := db.(*gorm.DB)
	var pdus []entity.PduInfo

	// 只查询有IP地址的PDU
	if err := gormDB.Where("ip != '' AND ip IS NOT NULL").Find(&pdus).Error; err != nil {
		return nil, 0, err
	}

	var snmpInfos []entity.SnmpInfo
	version := int(gosnmp.Version2c)
	for _, pdu := range pdus {
		if pdu.IP == "" {
			continue
		}

		snmpInfo := entity.SnmpInfo{
			IP:         pdu.IP,
			Community:  "public",    // 默认团体名
			Version:    version,     // 默认版本2
			Model:      entity.MPDU, // PDU模型
			Devicetype: entity.PDU,  // PDU类型
			Enable:     true,        // 默认启用
		}
		snmpInfos = append(snmpInfos, snmpInfo)
	}

	return snmpInfos, len(snmpInfos), nil
}

// syncSwitchInfo 同步交换机信息
func syncSwitchInfo(db interface{}) ([]entity.SnmpInfo, int, error) {
	gormDB := db.(*gorm.DB)
	var switches []entity.SwitchInfo

	// 只查询有IP地址的交换机
	if err := gormDB.Where("ip != '' AND ip IS NOT NULL").Find(&switches).Error; err != nil {
		return nil, 0, err
	}

	var snmpInfos []entity.SnmpInfo
	version := int(gosnmp.Version2c)
	for _, switchInfo := range switches {
		if switchInfo.IP == "" {
			continue
		}

		snmpInfo := entity.SnmpInfo{
			IP:         switchInfo.IP,
			Community:  "public",          // 默认团体名
			Version:    version,           // 默认版本2
			Model:      entity.H3C_S7506E, // 交换机模型
			Devicetype: entity.Switch,     // 交换机类型
			Enable:     true,              // 默认启用
		}
		snmpInfos = append(snmpInfos, snmpInfo)
	}

	return snmpInfos, len(snmpInfos), nil
}

// createSnmpOidsForNewDevice 为新增的SNMP设备创建对应的SnmpOid记录
func createSnmpOidsForNewDevice(tx *gorm.DB, ip string, model string) error {
	// 查询该model对应的所有ModelOid记录
	var modelOids []entity.ModelOid
	if err := tx.Where("model = ?", model).Find(&modelOids).Error; err != nil {
		return fmt.Errorf("查询ModelOid失败: %v", err)
	}

	if len(modelOids) == 0 {
		logging.Warnf("未找到model %s 对应的ModelOid记录", model)
		return nil // 没有对应的ModelOid不算错误
	}

	// 检查该IP是否已经有SnmpOid记录
	var existingOidCount int64
	if err := tx.Model(&entity.SnmpOid{}).Where("snmp_ip = ?", ip).Count(&existingOidCount).Error; err != nil {
		return fmt.Errorf("检查现有SnmpOid失败: %v", err)
	}

	if existingOidCount > 0 {
		logging.Infof("设备 %s 已存在SnmpOid记录，跳过创建", ip)
		return nil
	}

	// 根据ModelOid创建SnmpOid记录
	var snmpOids []entity.SnmpOid
	for _, modelOid := range modelOids {
		snmpOid := entity.SnmpOid{
			Snmpip:   ip,
			OidName:  modelOid.OidName,
			OidValue: modelOid.OidValue,
			Descr:    modelOid.Descr,
		}
		snmpOids = append(snmpOids, snmpOid)
	}

	// 批量插入SnmpOid记录
	if len(snmpOids) > 0 {
		if err := tx.CreateInBatches(&snmpOids, 100).Error; err != nil {
			return fmt.Errorf("批量插入SnmpOid失败: %v", err)
		}
		logging.Infof("为设备 %s (model: %s) 创建了 %d 条SnmpOid记录", ip, model, len(snmpOids))
	}

	return nil
}

// CompareSnmpSync 比对各类型设备的同步状态
// @Summary 比对设备同步状态
// @Description 比对各个类型设备与SNMP信息表的同步状态，显示哪些设备未同步
// @Tags 数据同步
// @Accept json
// @Produce json
// @Success 200 {object} common.Result{data=entity.CompareResponse} "比对成功"
// @Failure 500 {object} common.Result "比对失败"
// @Router /api/sync/compare [get]
func CompareSnmpSync(c *gin.Context) {
	db := utils.GetDB()
	if db == nil {
		common.ErrorResponse(c, http.StatusInternalServerError, "数据库连接失败")
		return
	}

	response := entity.CompareResponse{}

	// 1. 比对设备信息
	deviceComparison, err := compareDeviceSync(db)
	if err != nil {
		logging.Errorf("比对设备信息失败: %v", err)
		common.ErrorResponse(c, http.StatusInternalServerError, "比对设备信息失败: "+err.Error())
		return
	}
	response.DeviceComparison = deviceComparison

	// 2. 比对服务器信息
	serverComparison, err := compareServerSync(db)
	if err != nil {
		logging.Errorf("比对服务器信息失败: %v", err)
		common.ErrorResponse(c, http.StatusInternalServerError, "比对服务器信息失败: "+err.Error())
		return
	}
	response.ServerComparison = serverComparison

	// 3. 比对PDU信息
	pduComparison, err := comparePduSync(db)
	if err != nil {
		logging.Errorf("比对PDU信息失败: %v", err)
		common.ErrorResponse(c, http.StatusInternalServerError, "比对PDU信息失败: "+err.Error())
		return
	}
	response.PduComparison = pduComparison

	// 4. 比对交换机信息
	switchComparison, err := compareSwitchSync(db)
	if err != nil {
		logging.Errorf("比对交换机信息失败: %v", err)
		common.ErrorResponse(c, http.StatusInternalServerError, "比对交换机信息失败: "+err.Error())
		return
	}
	response.SwitchComparison = switchComparison

	// 5. 生成汇总信息
	response.Summary = entity.ComparisonSummary{
		TotalDevices: deviceComparison.TotalCount + serverComparison.TotalCount +
			pduComparison.TotalCount + switchComparison.TotalCount,
		SyncedDevices: deviceComparison.SyncedCount + serverComparison.SyncedCount +
			pduComparison.SyncedCount + switchComparison.SyncedCount,
		UnsyncedDevices: deviceComparison.UnsyncedCount + serverComparison.UnsyncedCount +
			pduComparison.UnsyncedCount + switchComparison.UnsyncedCount,
		ExcludedDevices: deviceComparison.ExcludedCount,
	}

	logging.Infof("设备同步状态比对完成，总计: %d, 已同步: %d, 未同步: %d, 排除: %d",
		response.Summary.TotalDevices, response.Summary.SyncedDevices,
		response.Summary.UnsyncedDevices, response.Summary.ExcludedDevices)

	common.SuccessResponse(c, response)
}

// compareDeviceSync 比对设备同步状态
func compareDeviceSync(db interface{}) (entity.DeviceComparisonResult, error) {
	gormDB := db.(*gorm.DB)
	result := entity.DeviceComparisonResult{}

	// 查询所有有IP的设备（包括车载设备用于统计排除数量）
	var allDevices []entity.DeviceInfo
	if err := gormDB.Where("ip != '' AND ip IS NOT NULL").Find(&allDevices).Error; err != nil {
		return result, err
	}

	// 查询非车载设备（实际需要同步的设备）
	var syncableDevices []entity.DeviceInfo
	if err := gormDB.Where("ip != '' AND ip IS NOT NULL AND (district IS NULL OR district != 4)").Find(&syncableDevices).Error; err != nil {
		return result, err
	}

	// 统计车载设备数量
	excludedCount := len(allDevices) - len(syncableDevices)

	// 查询已同步的设备IP
	var syncedIPs []string
	if err := gormDB.Model(&entity.SnmpInfo{}).Pluck("ip", &syncedIPs).Error; err != nil {
		return result, err
	}

	// 创建已同步IP的映射
	syncedIPMap := make(map[string]bool)
	for _, ip := range syncedIPs {
		syncedIPMap[ip] = true
	}

	// 分类设备
	var unsyncedDevices []entity.UnsyncedDeviceInfo
	syncedCount := 0

	for _, device := range syncableDevices {
		if syncedIPMap[device.IP] {
			syncedCount++
		} else {
			unsyncedDevice := entity.UnsyncedDeviceInfo{
				DeviceID:   device.DeviceID,
				DeviceName: device.DeviceName,
				IP:         device.IP,
				Type:       device.Type,
				District:   device.District,
			}
			unsyncedDevices = append(unsyncedDevices, unsyncedDevice)
		}
	}

	result.TotalCount = len(syncableDevices)
	result.SyncedCount = syncedCount
	result.UnsyncedCount = len(unsyncedDevices)
	result.ExcludedCount = excludedCount
	result.UnsyncedDevices = unsyncedDevices

	return result, nil
}

// compareServerSync 比对服务器同步状态
func compareServerSync(db interface{}) (entity.ServerComparisonResult, error) {
	gormDB := db.(*gorm.DB)
	result := entity.ServerComparisonResult{}

	// 查询所有有IP的服务器
	var servers []entity.ServerInfo
	if err := gormDB.Where("ip != '' AND ip IS NOT NULL").Find(&servers).Error; err != nil {
		return result, err
	}

	// 查询已同步的服务器IP
	var syncedIPs []string
	if err := gormDB.Model(&entity.SnmpInfo{}).Pluck("ip", &syncedIPs).Error; err != nil {
		return result, err
	}

	// 创建已同步IP的映射
	syncedIPMap := make(map[string]bool)
	for _, ip := range syncedIPs {
		syncedIPMap[ip] = true
	}

	// 分类服务器
	var unsyncedServers []entity.UnsyncedServerInfo
	syncedCount := 0

	for _, server := range servers {
		if syncedIPMap[server.IP] {
			syncedCount++
		} else {
			unsyncedServer := entity.UnsyncedServerInfo{
				ID:          server.ID,
				Name:        server.Name,
				IP:          server.IP,
				Type:        server.Type,
				StationName: server.StationName,
			}
			unsyncedServers = append(unsyncedServers, unsyncedServer)
		}
	}

	result.TotalCount = len(servers)
	result.SyncedCount = syncedCount
	result.UnsyncedCount = len(unsyncedServers)
	result.UnsyncedServers = unsyncedServers

	return result, nil
}

// comparePduSync 比对PDU同步状态
func comparePduSync(db interface{}) (entity.PduComparisonResult, error) {
	gormDB := db.(*gorm.DB)
	result := entity.PduComparisonResult{}

	// 查询所有有IP的PDU
	var pdus []entity.PduInfo
	if err := gormDB.Where("ip != '' AND ip IS NOT NULL").Find(&pdus).Error; err != nil {
		return result, err
	}

	// 查询已同步的PDU IP
	var syncedIPs []string
	if err := gormDB.Model(&entity.SnmpInfo{}).Pluck("ip", &syncedIPs).Error; err != nil {
		return result, err
	}

	// 创建已同步IP的映射
	syncedIPMap := make(map[string]bool)
	for _, ip := range syncedIPs {
		syncedIPMap[ip] = true
	}

	// 分类PDU
	var unsyncedPdus []entity.UnsyncedPduInfo
	syncedCount := 0

	for _, pdu := range pdus {
		if syncedIPMap[pdu.IP] {
			syncedCount++
		} else {
			unsyncedPdu := entity.UnsyncedPduInfo{
				ID:          pdu.ID,
				Name:        pdu.Name,
				Number:      pdu.Number,
				IP:          pdu.IP,
				StationName: pdu.StationName,
			}
			unsyncedPdus = append(unsyncedPdus, unsyncedPdu)
		}
	}

	result.TotalCount = len(pdus)
	result.SyncedCount = syncedCount
	result.UnsyncedCount = len(unsyncedPdus)
	result.UnsyncedPdus = unsyncedPdus

	return result, nil
}

// compareSwitchSync 比对交换机同步状态
func compareSwitchSync(db interface{}) (entity.SwitchComparisonResult, error) {
	gormDB := db.(*gorm.DB)
	result := entity.SwitchComparisonResult{}

	// 查询所有有IP的交换机
	var switches []entity.SwitchInfo
	if err := gormDB.Where("ip != '' AND ip IS NOT NULL").Find(&switches).Error; err != nil {
		return result, err
	}

	// 查询已同步的交换机IP
	var syncedIPs []string
	if err := gormDB.Model(&entity.SnmpInfo{}).Pluck("ip", &syncedIPs).Error; err != nil {
		return result, err
	}

	// 创建已同步IP的映射
	syncedIPMap := make(map[string]bool)
	for _, ip := range syncedIPs {
		syncedIPMap[ip] = true
	}

	// 分类交换机
	var unsyncedSwitches []entity.UnsyncedSwitchInfo
	syncedCount := 0

	for _, switchInfo := range switches {
		if syncedIPMap[switchInfo.IP] {
			syncedCount++
		} else {
			unsyncedSwitch := entity.UnsyncedSwitchInfo{
				ID:          switchInfo.ID,
				Name:        switchInfo.Name,
				IP:          switchInfo.IP,
				StationName: switchInfo.StationName,
			}
			unsyncedSwitches = append(unsyncedSwitches, unsyncedSwitch)
		}
	}

	result.TotalCount = len(switches)
	result.SyncedCount = syncedCount
	result.UnsyncedCount = len(unsyncedSwitches)
	result.UnsyncedSwitches = unsyncedSwitches

	return result, nil
}
